package com.mazaiting.redisson.config;

import com.mazaiting.redis.config.RedisConfig;
import com.mazaiting.redis.manager.TtlRedisCacheManager;
import com.mazaiting.redisson.service.IRedissonService;
import com.mazaiting.redisson.service.impl.RedissonServiceImpl;
import org.redisson.api.RedissonClient;
import org.redisson.spring.data.connection.RedissonConnectionFactory;
import org.redisson.spring.starter.RedissonAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;


/**
 * 分布式锁配置
 *
 * @author mazaiting
 * @create_time 2022/3/30 19:25
 */
@Configuration
@AutoConfigureBefore(value = {RedisConfig.class, RedissonAutoConfiguration.class})
public class RedissonConfig {

    /**
     * Redis 模板
     *
     * @param redissonConnectionFactory 连接池工厂
     * @param redisSerializer           序列号器
     * @return RedisTemplate<String, Object>
     */
    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(
            RedisConnectionFactory redissonConnectionFactory,
            RedisSerializer<Object> redisSerializer) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接池工厂
        redisTemplate.setConnectionFactory(redissonConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(redisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 连接池工厂
     *
     * @param redissonClient redisson 客户端
     * @return 连接池工厂
     */
    @Bean
    @ConditionalOnMissingBean(RedissonConnectionFactory.class)
    public RedisConnectionFactory redissonConnectionFactory(RedissonClient redissonClient) throws Exception {
        RedissonConnectionFactory connectionFactory = new RedissonConnectionFactory(redissonClient);
        connectionFactory.afterPropertiesSet();
        return connectionFactory;
    }

    /**
     * 缓存管理
     *
     * @param connectionFactory 连接池工厂
     * @param redisSerializer   序列号器
     * @return RedisCacheManager
     */
    @Bean
    @ConditionalOnMissingBean(RedisCacheManager.class)
    public RedisCacheManager redisCacheManager(
            RedisConnectionFactory connectionFactory,
            RedisSerializer<Object> redisSerializer) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory);
        //设置Redis缓存有效期为1天
        RedisCacheConfiguration redisCacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                        .entryTtl(Duration.ofMinutes(15));
        return new TtlRedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

    /**
     * 提供 Redis 服务
     *
     * @return RedisServiceImpl
     */
    @Bean
    @ConditionalOnMissingBean(name = "redissonService")
    public IRedissonService redissonService() {
        return new RedissonServiceImpl();
    }

}
